`timescale 1ns/1ns
`define DATA_WIDTH 256

module DBLU_coz(input clk,
				input rst_n,
				input enable,
				input error,
				input MM_end_flag,
				output reg MM_enable,
				output reg func,
				output reg [21:0] r_sel,
				output reg [7:0] M_sel_a,
				output reg [7:0] M_sel_b,
				output reg [7:0] A_sel_a,
				output reg [7:0] A_sel_b,
				output reg end_flag
			   );
			   
reg [18:0] state,next_state;

parameter IDLE  = 19'b000_0000_0000_0000_0001,
		  REG   = 19'b000_0000_0000_0000_0010,
		  STEP1 = 19'b000_0000_0000_0000_0100,
		  STEP2 = 19'b000_0000_0000_0000_1000,
		  STEP3 = 19'b000_0000_0000_0001_0000,
		  STEP4 = 19'b000_0000_0000_0010_0000,
		  STEP5 = 19'b000_0000_0000_0100_0000,
		  STEP6 = 19'b000_0000_0000_1000_0000,
		  STEP7 = 19'b000_0000_0001_0000_0000,
		  STEP8 = 19'b000_0000_0010_0000_0000,
		  STEP9 = 19'b000_0000_0100_0000_0000,
		  STEP10= 19'b000_0000_1000_0000_0000,
		  STEP11= 19'b000_0001_0000_0000_0000,
		  STEP12= 19'b000_0010_0000_0000_0000,
		  STEP13= 19'b000_0100_0000_0000_0000,
		  STEP14= 19'b000_1000_0000_0000_0000,
		  STEP15= 19'b001_0000_0000_0000_0000,
		  STEP16= 19'b010_0000_0000_0000_0000,
		  STEP17= 19'b100_0000_0000_0000_0000;
		  

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		state <= IDLE;
	end
	else if(error)
	begin
		state <= IDLE;
	end
	else
	begin
		state <= next_state;
	end
end

always @(*)
begin
	case(state)
	IDLE   :
			begin
				if((enable) & (!end_flag))
					next_state = REG;
				else
					next_state = IDLE;
		 	end
	REG    :
			begin
				next_state = STEP1;
			end
	STEP1  :
			begin
				if(MM_end_flag)
					next_state = STEP2;
				else
					next_state = STEP1;
			end
	STEP2  :
			begin
				next_state = STEP3;
			end
	STEP3  :
			begin
				if(MM_end_flag)
					next_state = STEP4;
				else
					next_state = STEP3;
			end
	STEP4  :
			begin
				if(MM_end_flag)
					next_state = STEP5;
				else
					next_state = STEP4;
			end	
	STEP5  :
			begin
				if(MM_end_flag)
					next_state = STEP6;
				else
					next_state = STEP5;
			end		
	STEP6  :
		 	begin
				next_state = STEP7;
			end	
	STEP7  :
			begin
				next_state = STEP8;
			end	
	STEP8  :
			begin
				next_state = STEP9;
			end	
	STEP9  :
			begin
				next_state = STEP10;
			end	
	STEP10 :
			begin
				next_state = STEP11;
			end	
	STEP11 :
			begin
				if(MM_end_flag)
					next_state = STEP12;
				else
					next_state = STEP11;
			end
	STEP12 :
			begin
				next_state = STEP13;
			end
	STEP13 :
			begin
				next_state = STEP14;
			end	
	STEP14 :
			begin
				if(MM_end_flag)
					next_state = STEP15;
				else
					next_state = STEP14;
			end
	STEP15 :
			begin
				next_state = STEP16;
			end
	STEP16 :
			begin
				next_state = STEP17;
			end
	STEP17 :
			begin
				next_state = IDLE;
			end
	default:
			begin
				next_state = IDLE;
			end
	endcase
end

always @(*)
begin
		case(state)
		/*IDLE:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b0;
				A_sel_b = 8'b0;
			end
		REG:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b0;
				A_sel_b = 8'b0;
			end
		*/
		STEP1:
			begin
				M_sel_a = 8'b00000100;//t2
				M_sel_b = 8'b00000100;//t2
				A_sel_a = 8'b0;
				A_sel_b = 8'b0;
			end
		STEP2:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00000010;//t1
				A_sel_b = 8'b00000100;//t2
			end
		STEP3:
			begin
				M_sel_a = 8'b00010000;//t4
				M_sel_b = 8'b00010000;//t4
				A_sel_a = 8'b0;
				A_sel_b = 8'b0;	
			end
		STEP4:
			begin
				M_sel_a = 8'b00000010;//t1
				M_sel_b = 8'b00000010;//t1
				A_sel_a = 8'b0;
				A_sel_b = 8'b0;		
			end
		STEP5:
			begin
				M_sel_a = 8'b00000100;//t2
				M_sel_b = 8'b00000100;//t2
				A_sel_a = 8'b00010000;//t4
				A_sel_b = 8'b00100000;//t5
			end
		STEP6:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00010000;//t4
				A_sel_b = 8'b00000100;//t2		
			end
		STEP7:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00010000;//t4
				A_sel_b = 8'b00010000;//t4				
			end
		STEP8:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00000001;//t0
				A_sel_b = 8'b00100000;//t5					
			end
		STEP9:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00100000;//t5
				A_sel_b = 8'b00100000;//t5	
			end
		STEP10:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00000001;//t0
				A_sel_b = 8'b00100000;//t5			
			end
		STEP11:
			begin
				M_sel_a = 8'b00000001;//t0
				M_sel_b = 8'b00000001;//t0
				A_sel_a = 8'b00000010;//t1
				A_sel_b = 8'b00000010;//t1		
			end
		STEP12:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00010000;//t4
				A_sel_b = 8'b00100000;//t5				
			end
		STEP13:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00000010;//t1
				A_sel_b = 8'b00010000;//t4						
			end
		STEP14:
			begin
				M_sel_a = 8'b00100000;//t5
				M_sel_b = 8'b00000001;//t0
				A_sel_a = 8'b00000100;//t2
				A_sel_b = 8'b00000100;//t2						
			end
		STEP15:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00000100;//t2
				A_sel_b = 8'b00000100;//t2				
			end
		STEP16:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00000100;//t2
				A_sel_b = 8'b00000100;//t2			
			end
		STEP17:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b00100000;//t5
				A_sel_b = 8'b00000100;//t2	
			end
		default:
			begin
				M_sel_a = 8'b0;
				M_sel_b = 8'b0;
				A_sel_a = 8'b0;
				A_sel_b = 8'b0;
			end
		endcase
end

always @(*)
begin
		case(state)
		IDLE  : 
				r_sel = 22'b0;
		REG	  :
				r_sel = 22'b000_00_000_000_000_100_100_11;
		STEP1 :
				r_sel = 22'b000_00_000_000_000_010_000_00;
		STEP2 :
				r_sel = 22'b000_00_000_001_000_000_000_00;
		STEP3 :
				r_sel = 22'b000_00_000_010_000_000_000_00;		
		STEP4 :
				r_sel = 22'b000_00_010_000_000_000_000_00;	
		STEP5 :
				if(MM_end_flag)
				r_sel = 22'b000_00_000_001_000_010_000_00;
				else
				r_sel = 22'b000_00_000_000_000_010_000_00;
		STEP6 :
				r_sel = 22'b000_00_000_001_000_000_000_00;
		STEP7 :
				r_sel = 22'b000_00_000_000_000_000_001_00;	
		STEP8 :
				r_sel = 22'b000_00_000_000_000_000_000_01;	
		STEP9 :
				r_sel = 22'b000_00_001_000_000_000_000_00;	
		STEP10:
				r_sel = 22'b000_00_000_000_000_000_000_01;	
		STEP11:
				r_sel = 22'b000_00_001_010_000_000_000_00;
		STEP12:
				r_sel = 22'b000_00_000_001_000_000_000_00;
		STEP13:
				r_sel = 22'b000_00_001_000_000_000_000_00;
		STEP14:
				if(MM_end_flag)
				r_sel = 22'b000_00_010_000_000_001_000_00;	
				else
				r_sel = 22'b000_00_010_000_000_000_000_00;
		STEP15:
				r_sel = 22'b000_00_000_000_000_001_000_00;	
		STEP16:
				r_sel = 22'b000_00_000_000_000_001_000_00;	
		STEP17:
				r_sel = 22'b000_00_001_000_000_000_000_00;
		default:
				r_sel = 22'b0;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		MM_enable <= 1'b0;
	end
	else
	begin
		case(next_state)
		IDLE  :
					MM_enable <= 1'b0;
		REG	  :
					MM_enable <= 1'b0;
		STEP1 :
				if(state == REG)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP2 :
					MM_enable <= 1'b0;
		STEP3 :
				if(state == STEP2)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP4 :
				if(state == STEP3)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP5 :
				if(state == STEP4)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;		
		STEP6 :	
					MM_enable <= 1'b0;
		STEP7 :
					MM_enable <= 1'b0;
		STEP8 :
					MM_enable <= 1'b0;
		STEP9 :
					MM_enable <= 1'b0;
		STEP10:
					MM_enable <= 1'b0;					
		STEP11:
				if(state == STEP10)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP12:
					MM_enable <= 1'b0;	
		STEP13:
					MM_enable <= 1'b0;	
		STEP14:
				if(state == STEP13)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP15:
					MM_enable <= 1'b0;
		STEP16:
					MM_enable <= 1'b0;
		STEP17:
					MM_enable <= 1'b0;
		default:
					MM_enable <= 1'b0;
		endcase
	end
end

always @(*)
begin
		case(state)
		/*
		IDLE  :
					func = 1'b0;
		REG	  :
					func = 1'b0;
		STEP1 :
					func = 1'b0;
		STEP2 :
					func = 1'b0;
		STEP3 :
					func = 1'b0;
		STEP4 :
					func = 1'b0;
		*/
		STEP5 :
					func = 1'b1;	
		STEP6 :	
					func = 1'b1;
		/*
		STEP7 :
					func = 1'b0;
		STEP8 :
					func = 1'b0;
		STEP9 :
					func = 1'b0;
		STEP10:
					func = 1'b0;					
		STEP11:
					func = 1'b0;
		*/
		STEP12:
					func = 1'b1;	
		STEP13:
					func = 1'b1;	
		/*
		STEP14:
					func = 1'b0;
		STEP15:
					func = 1'b0;
		STEP16:
					func = 1'b0;
		*/
		STEP17:
					func = 1'b1;
		default:
					func = 1'b0;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		end_flag <= 1'b0;
	end
	else if(state == STEP17)
	begin
		end_flag <= 1'b1;
	end
	else
	begin
		end_flag <= 1'b0;
	end
end

endmodule